package cn.jolyoulu.common.web.security.interceptors;

import cn.jolyoulu.common.web.excption.GlobalException;
import cn.jolyoulu.common.web.security.entity.LoginUser;
import cn.jolyoulu.common.web.security.enums.SecurityExpType;
import cn.jolyoulu.common.web.security.permission.LogicType;
import cn.jolyoulu.common.web.security.permission.Permission;
import cn.jolyoulu.common.web.security.utils.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;


import java.util.*;

/**
 * @Author LuZhouJin
 * @Date 2023/3/17
 * 用户权限认证拦截器
 */
@Slf4j
@Component
public class UserPermissionInterceptor implements HandlerInterceptor {

    @Value("${spring.profiles.active}")
    private String active;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        //获取请求的方法
        HandlerMethod h = (HandlerMethod) handler;
        Permission permission = h.getMethodAnnotation(Permission.class);
        if (Objects.isNull(permission)){
            return true;
        }

        if (!permission.flag()){ //如果关闭，直接放行
            return true;
        }

        //开发环境下，超级管理员角色直接放行
        if (active.equals("dev") && devRoleCheck()){
            log.debug("@Permission ==> 开发环境,Admin角色不校验权限");
            return true;
        }

        if (!checkPerm(permission)){ //无权限时抛异常
            throw new GlobalException(SecurityExpType.OPERATION_FORBIDDEN);
        }
        return true;
    }

    /**
     * 权限校验
     */
    private boolean checkPerm(Permission permission) {
        //获取用户的权限
        LoginUser<?> user = SecurityUtils.getLoginUser();
        if (Objects.isNull(user)){
            throw new GlobalException(SecurityExpType.TOKEN_NO_AVAIL);
        }

        LogicType type = permission.type();
        String[] methodPerm = permission.value();



        HashSet<String> methodPermSet = new HashSet<>(Arrays.asList(methodPerm));

        Set<String> userPermSet = user.getPermissions();
        switch (type){
            case AND:
                for (String perm : methodPermSet) {
                    //其中一个没有就没权限
                    if (!userPermSet.contains(perm)){
                        return false;
                    }
                }
                return true;
            case OR:
                for (String perm : methodPermSet) {

                    //有一个就是有权限
                    if (userPermSet.contains(perm)){
                        return true;
                    }
                }
                return false;
            default:
                return false;
        }
    }

    /**
     * 不是测试类型角色，不需要进行权限校验
     */
    private boolean devRoleCheck(){
        //获取用户的权限
        LoginUser<?> user = SecurityUtils.getLoginUser();
        Set<String> roles = user.getRoles();
        if (roles.contains("测试类型")){
            return true;
        }
        return false;
    }
}
